import codecs
import os
import re
import sys
import win32com.client
import pythoncom
import traceback

# TODO - posprzatac logowanie
# TODO - posprzatac run_before i run_after

EOL="\n"

def get_egp_app():
	import time
	for i in range(6):
		try:
			pythoncom.CoInitialize()
			app = win32com.client.Dispatch("SASEGObjectModel.Application.4.3")
			return app
		except Exception,e:
			time.sleep(10)
	raise e

def run_code(proj,code,log_path="",print_errors=False):
	pid_str="\n\nPID="+str(os.getpid())+"\n\n"
	try:
		if type(code)==type(""):
			codestr=code
			code=proj.CodeCollection.Add()
			code.Text = codestr
		code.Run()
		try:
			log = code.Log.Text
		except Exception,e:
			log = "WARNING: RIVULET cannot access code.Log.Text\n" +str(e)
		if log_path:
			codecs.open(log_path,"a","utf-8").write(pid_str+log)
		else:
			print log.encode('ascii','replace')
		errors = re.findall("ERROR[ ]?[0-9-]*:.*\n.*\n.*",log)
	except Exception,e:
		errors=[traceback.format_exc()]
	if errors:
		if log_path:
			codecs.open(log_path,"a","utf-8").write("\n\n\n".join(errors))
		if print_errors:
			sys.stderr.write(EOL.join(errors))
		return 1
	else:
		return 0

def close_proj(proj):
	try:
		proj.Close()
	except:
		pass

def run_all_ordered_lists(egp_path,run_before="",run_after="",log_path=""):
	"""Run all OrderedLists of SAS EG 4.3 project. Logs to stdout and stderr.
	TODO: sort Lists by names
	"""
	app = get_egp_app()
	proj = app.Open(egp_path,"")
	if run_before:
		err = run_code(proj,run_before,log_path)
		if err:
			close_proj(proj)
			return 1
	for pi in proj.ProjectItems:
		print "ProjectItem", pi,pi.Type,pi.Name.encode('ascii','replace')
		if pi.Type==4:
			for list_item in pi.Items:
				if list_item.Type==20:
					print "ListItem",list_item.Type,list_item.Name.encode('ascii','replace')
					for code in list_item.Items:
						print "RUN",code.Type,code.Name.encode('ascii','replace'),
						err = run_code(proj,code,log_path)
						if err:
							close_proj(proj)
							return 2
	if run_after:
		err = run_code(proj,run_after,log_path)
		if err:
			close_proj(proj)
			return 3  
	close_proj(proj)
	return 0

def run_ordered_list(egp_path,list_name,run_before="",run_after="",log_path=""):
	"""Run OrderedLists "list_name" of SAS EG 4.3 project. Logs to stdout and stderr.
	"""
	app = get_egp_app()
	proj = app.Open(egp_path,"")
	rc=10 # list not found
	if run_before:
		err = run_code(proj,run_before,log_path)
		if err:
			close_proj(proj)
			return 1
	for pi in proj.ProjectItems:
		print "ProjectItem", pi,pi.Type,pi.Name.encode('ascii','replace')
		if pi.Type==4:
			for list_item in pi.Items:
				if list_item.Type==20:
					n = list_item.Name.encode('ascii','replace')
					if n.lower().strip()<>list_name.lower().strip():
						continue
					print "ListItem",list_item.Type,list_item.Name.encode('ascii','replace')
					for code in list_item.Items:
						print "RUN",code.Type,code.Name.encode('ascii','replace'),
						err = run_code(proj,code,log_path)
						if err:
							close_proj(proj)
							return 2
						else:
							rc=0 # ok
	if run_after:
		err = run_code(proj,run_after,log_path)
		if err:
			close_proj(proj)
			return 3  
	close_proj(proj)
	return rc

def run_str(code,run_before="",run_after="",log_path=""):
	app = get_egp_app()
	# app.SetActiveProfile("My Server")
	proj = app.New()
	if run_before:
		err = run_code(proj,run_before,log_path)
		if err:
			close_proj(proj)
			return 1	
	err = run_code(proj,code,log_path)
	if err:
		close_proj(proj)
		return 2
	if run_after:
		err = run_code(proj,run_after,log_path)
		if err:
			close_proj(proj)
			return 3
	close_proj(proj)
	return 0

import sys
def run_from_cmdline():
	egp_path = sys.argv[1]
	log_path = sys.argv[2]
	listname = sys.argv[3]
	rb_path = sys.argv[4]
	ra_path = sys.argv[5]
	if rb_path=='.':
		rb=""
	else:
		rb=open(rb_path,'r').read()
	if ra_path=='.':
		ra=""
	else:
		ra=open(ra_path,'r').read()
	if listname=='.':
		rc=run_all_ordered_lists(egp_path,run_before=rb,run_after=ra,log_path=log_path)
	else:
		rc=run_ordered_list(egp_path,listname,run_before=rb,run_after=ra,log_path=log_path)
	exit(rc)

if __name__=="__main__":
	run_from_cmdline()

"""
a = win32com.client.Dispatch("SASEGObjectModel.Application.4") # Application.4.3" dla EG 4.3
p = a.Open(r"L:\M_OBARSKI\ole\test1_91.egp","")
c=p.CodeCollection.Add()
c.Text = '%let DATA="12jun1981"d;'
c.Run()
print c.Log.Text
if True:
	for pi in p.ProjectItems:
		print "ProjectItem", pi,pi.Type,pi.Name.encode('ascii','replace')
		if pi.Type==4:
			for x in pi.Items:
				#print "ListItem",x.Type,x.Name.encode('ascii','replace')
				if x.Type==20:
					print "Lista",x.Type,x.Name.encode('ascii','replace')
					for c in x.Items:
						print "RUN",c.Type,c.Name.encode('ascii','replace'),
						#if c.Type==8:
						#	print c.TaskCode.Text.encode('ascii','replace')
						try:
							c.Run()
							log = c.Log.Text.encode('ascii','replace')
							errors = re.findall("ERROR[ ]?[0-9-]*:.+\n.+\n.+",log)
						except Exception,e:
							errors=[e]
						if errors:
							print "ERROR"
							print errors
						else:
							print "OK"
						#print "\t"+'\n\t'.join(log.split("\n"))
						#print [log]
	for t in p.Tasks:
		print "Task",t
#p.Save()
p.Close()
"""
